﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using YArchitech.LIB;
using YArchitech.Revit;
using libxl;

namespace YArchitech.HYSpace
{
	public class EstimateLoadOperate
	{
		public EstimateLoadOperate(UIDocument uiDocument)
		{
			this.UiDoc = uiDocument;
			this.doc = this.UiDoc.Document;
			this.sel = this.UiDoc.Selection;
			this.searchMessage = "";
		}

		public List<LoadEstimateParam> SearchElementSet(bool beSpace)
		{
			List<LoadEstimateParam> list = new List<LoadEstimateParam>();
			if (beSpace)
			{
				list = this.SearchSpaceElements();
				if (list.Count < 1 && string.IsNullOrEmpty(this.searchMessage))
				{
					this.searchMessage = "请使用盈建科“创建空间”功能后，再进行负荷估算！";
				}
			}
			else
			{
				list = this.SearchRoomElements(this.HeatIndex, this.CoolIndex);
				if (list.Count < 1 && string.IsNullOrEmpty(this.searchMessage))
				{
					this.searchMessage = "没有可以计算的房间！";
				}
			}
			return list;
		}

		private List<LoadEstimateParam> SearchSpaceElements()
		{
			List<LoadEstimateParam> list = new List<LoadEstimateParam>();
			List<Element> list2 = this.SearchRoomOrSpace(true);
			List<Element> collection = this.SearchLinkRoomOrSpace(true);
			list2.AddRange(collection);
			if (list2.Count == 0)
			{
				return list;
			}
			int num = 0;
			foreach (Element element in list2)
			{
				Space space = element as Space;
				if (space != null)
				{
					List<Curve> spaceOrRoomBoundaryCurve = YJKRevitTools.GetSpaceOrRoomBoundaryCurve(space);
					if (spaceOrRoomBoundaryCurve != null && spaceOrRoomBoundaryCurve.Count >= 1)
					{
						num++;
						Parameter parameter = space.GetParameter("盈建科-总冷指标(W/m^2)");
						Parameter parameter2 = space.GetParameter("盈建科-总热指标(W/m^2)");
						if (parameter != null && parameter2 != null && parameter.HasValue && parameter2.HasValue)
						{
							double num2 = parameter.AsDouble();
							double num3 = parameter2.AsDouble();
							if (num2 >= 0.1 && num3 >= 0.1)
							{
								list.Add(new LoadEstimateParam
								{
									BeSpace = true,
									RoomName = space.Name,
									RoomArea = UnitConvert.AreaConverFromAPI(space.Document, space.Area),
									HeatIndex = num3,
									CoolIndex = num2,
									ElemId = space.Id.IntegerValue,
									ElemDocument = space.Document
								});
							}
						}
					}
				}
			}
			if (num == 0)
			{
				this.searchMessage = "没有可以计算的空间！";
			}
			return list;
		}

		private List<LoadEstimateParam> SearchRoomElements(double heatIndex, double coolIndex)
		{
			List<LoadEstimateParam> list = new List<LoadEstimateParam>();
			List<Element> list2 = this.SearchRoomOrSpace(false);
			List<Element> collection = this.SearchLinkRoomOrSpace(false);
			list2.AddRange(collection);
			if (list2.Count == 0)
			{
				return list;
			}
			foreach (Element element in list2)
			{
				Room room = element as Room;
				if (room != null)
				{
					List<Curve> spaceOrRoomBoundaryCurve = YJKRevitTools.GetSpaceOrRoomBoundaryCurve(room);
					if (spaceOrRoomBoundaryCurve != null && spaceOrRoomBoundaryCurve.Count >= 1)
					{
						list.Add(new LoadEstimateParam
						{
							BeSpace = false,
							RoomName = room.Name,
							RoomArea = UnitConvert.AreaConverFromAPI(room.Document, room.Area),
							HeatIndex = heatIndex,
							CoolIndex = coolIndex,
							ElemId = room.Id.IntegerValue,
							ElemDocument = room.Document
						});
					}
				}
			}
			return list;
		}

		private List<Element> SearchRoomOrSpace(bool beSpace)
		{
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.doc, this.doc.ActiveView.Id);
			BuiltInCategory builtInCategory = BuiltInCategory.OST_MEPSpaces;
			if (!beSpace)
			{
				builtInCategory = BuiltInCategory.OST_Rooms;
			}
			return filteredElementCollector.OfCategory(builtInCategory).ToList<Element>();
		}

		private List<Element> SearchLinkRoomOrSpace(bool beSpace)
		{
			IEnumerable<Document> linkDocuments = this.doc.GetLinkDocuments();
			FilteredElementCollector filteredElementCollector = null;
			List<Element> list = new List<Element>();
			List<Element> list2 = new List<Element>();
			if (linkDocuments != null)
			{
				foreach (Document document in linkDocuments)
				{
					if (document != null)
					{
						filteredElementCollector = new FilteredElementCollector(document);
						if (filteredElementCollector != null)
						{
							BuiltInCategory builtInCategory = BuiltInCategory.OST_MEPSpaces;
							if (!beSpace)
							{
								builtInCategory = BuiltInCategory.OST_Rooms;
							}
							list2 = filteredElementCollector.OfCategory(builtInCategory).ToList<Element>();
							list.AddRange(list2);
							double elevation = this.doc.ActiveView.GenLevel.Elevation;
							foreach (Element element in list2)
							{
								if (Math.Abs(element.GetYJKLevel().Elevation - elevation) > 0.016404199475065617)
								{
									list.Remove(element);
								}
							}
						}
					}
				}
			}
			return list;
		}

		public bool ExportExcel(List<LoadEstimateParam> listLoad)
		{
			bool result = true;
			try
			{
				Book book = new BinBook();
				book.setKey("Beijing YArchitech Tongxing Technology Co.,Ltd", "windows-282b2c0f08cbe70966b4616ea0i8d7n0");
				Sheet sheet = book.addSheet("冷热负荷估算表");
				Format tabelFormat = this.GetTabelFormat(book);
				Format titleFormat = this.GetTitleFormat(book, tabelFormat);
				this.SetCellWidth(sheet);
				int rowIndex = 0;
				this.WriteTitle(sheet, rowIndex, titleFormat);
				this.WriteTable(sheet, rowIndex, tabelFormat, listLoad);
				string text = Path.Combine(Product.UserDataLocation, "冷热负荷计算表.xls");
				book.save(text);
				Process.Start(text);
			}
			catch (System.Exception ex)
			{
				string message = ex.Message;
			}
			return result;
		}

		private void WriteTitle(Sheet sheet, int rowIndex, Format format)
		{
			List<string> tableTitleValues = this.GetTableTitleValues();
			for (int i = 0; i < tableTitleValues.Count; i++)
			{
				this.ExportText(sheet, rowIndex, i, i, tableTitleValues[i], format);
			}
		}

		private void SetCellWidth(Sheet sheet)
		{
			sheet.setCol(0, 15.0);
			sheet.setCol(1, 25.0);
			sheet.setCol(2, 25.0);
			sheet.setCol(3, 25.0);
			sheet.setCol(4, 25.0);
			sheet.setCol(5, 25.0);
		}

		private void WriteTable(Sheet sheet, int rowIndex, Format format, List<LoadEstimateParam> listLoad)
		{
			foreach (LoadEstimateParam loadEstimateParam in listLoad)
			{
				rowIndex++;
				this.ExportText(sheet, rowIndex, 0, 0, loadEstimateParam.RoomName, format);
				this.ExportText(sheet, rowIndex, 1, 1, loadEstimateParam.RoomArea.ToString(), format);
				this.ExportText(sheet, rowIndex, 2, 2, loadEstimateParam.HeatIndex.ToString(), format);
				this.ExportText(sheet, rowIndex, 3, 3, loadEstimateParam.HeatLoad.ToString(), format);
				this.ExportText(sheet, rowIndex, 4, 4, loadEstimateParam.CoolIndex.ToString(), format);
				this.ExportText(sheet, rowIndex, 5, 5, loadEstimateParam.CoolLoad.ToString(), format);
			}
		}

		private List<string> GetTableTitleValues()
		{
			return new List<string>
			{
				"房间名称",
				"房间面积（㎡）",
				"热指标（W/㎡）",
				"热负荷（W）",
				"冷指标（W/㎡）",
				"冷负荷（W）"
			};
		}

		private void ExportText(Sheet sheet, int rowIndex, int colStart, int colEnd, string value, Format format)
		{
			sheet.setMerge(rowIndex, rowIndex, colStart, colEnd);
			for (int i = colStart; i <= colEnd; i++)
			{
				sheet.setCellFormat(rowIndex, i, format);
			}
			sheet.writeStr(rowIndex, colStart, value);
		}

		private void InitialLibxlFormat(Book book)
		{
			Font font = book.addFont();
			font.size = 10;
			Format format = book.addFormat();
			format.alignH = AlignH.ALIGNH_CENTER;
			format.alignV = AlignV.ALIGNV_CENTER;
			format.font = font;
			Format format2 = book.addFormat(format);
			format2.setBorder(BorderStyle.BORDERSTYLE_THIN);
			book.addFormat(format2).alignH = AlignH.ALIGNH_LEFT;
			book.addFormat(format2).alignH = AlignH.ALIGNH_RIGHT;
			Font font2 = book.addFont();
			font2.size = 12;
			font2.name = "黑体";
			book.addFormat(format).font = font2;
		}

		private Format GetTabelFormat(Book book)
		{
			Font font = book.addFont();
			font.size = 10;
			Format format = book.addFormat();
			format.alignH = AlignH.ALIGNH_CENTER;
			format.alignV = AlignV.ALIGNV_CENTER;
			format.font = font;
			Format format2 = book.addFormat(format);
			format2.setBorder(BorderStyle.BORDERSTYLE_THIN);
			return format2;
		}

		private Format GetTitleFormat(Book book, Format baseFormat)
		{
			Font font = book.addFont();
			font.size = 12;
			font.name = "黑体";
			Format format = book.addFormat(baseFormat);
			format.font = font;
			return format;
		}

		public bool MarkText(List<LoadEstimateParam> listLoad)
		{
			bool result = true;
			Transaction transaction = new Transaction(this.doc, "估算负荷标注");
			try
			{
				transaction.Start();
				foreach (LoadEstimateParam loadParam in listLoad)
				{
					this.MarkRoomOrSpaceText(loadParam);
				}
				transaction.Commit();
			}
			catch (System.Exception ex)
			{
				string message = ex.Message;
				transaction.RollBack();
			}
			return result;
		}

		private bool MarkRoomOrSpaceText(LoadEstimateParam loadParam)
		{
			bool result = true;
			try
			{
				SubTransaction subTransaction = new SubTransaction(this.doc);
				ElementId elementId = new ElementId(loadParam.ElemId);
				XYZ xyz = null;
				Parameter parameter = null;
				if (loadParam.BeSpace)
				{
					Space space = loadParam.ElemDocument.GetElementById(elementId) as Space;
					xyz = this.GetRefPoint(space);
					parameter = space.GetParameter(BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS);
				}
				else
				{
					Room room = loadParam.ElemDocument.GetElementById(elementId) as Room;
					xyz = this.GetRefPoint(room);
					if (loadParam.ElemDocument.IsLinked)
					{
						xyz = this.doc.GetLinkedDocument(elementId).GetPointInLinkDocument(xyz);
					}
					parameter = room.GetParameter(BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS);
				}
				if (parameter != null && !string.IsNullOrEmpty(parameter.AsString()))
				{
					try
					{
						subTransaction = new SubTransaction(this.doc);
						subTransaction.Start();
						ElementId elementId2 = new ElementId(Convert.ToInt32(parameter.AsString()));
						Element elementById = this.doc.GetElementById(elementId2);
						if (elementById != null)
						{
							this.doc.DeleteElement(elementById);
						}
						parameter.Set(" ");
						subTransaction.Commit();
					}
					catch (System.Exception ex)
					{
						string message = ex.Message;
						subTransaction.RollBack();
					}
				}
				XYZ origin = xyz;
				XYZ baseVec = new XYZ(1.0, 0.0, 0.0);
				XYZ upVec = new XYZ(0.0, 1.0, 0.0);
				List<string> list = new List<string>();
				list.Add("房间名称：" + loadParam.RoomName);
				list.Add("房间面积：" + loadParam.RoomArea + "㎡");
				list.Add("热指标：" + loadParam.HeatIndex + "W/㎡");
				list.Add("热负荷：" + loadParam.HeatLoad + "W");
				list.Add("冷指标：" + loadParam.CoolIndex + "W/㎡");
				list.Add("冷负荷：" + loadParam.CoolLoad + "W");
				string strText = string.Concat(new string[]
				{
					list[0],
					"\n",
					list[1],
					"\n",
					list[2],
					"\n",
					list[3],
					"\n",
					list[4],
					"\n",
					list[5]
				});
				double textWidth = this.GetTextWidth(list);
				try
				{
					subTransaction = new SubTransaction(this.doc);
					subTransaction.Start();
                    TextNote textNode = this.doc.GetTextNode(this.doc.ActiveView, origin, baseVec, upVec, 0.0032808398950131233, (TextAlignFlags)64, strText, textWidth);
					this.doc.Regenerate();
					subTransaction.Commit();
					if (!loadParam.ElemDocument.IsLinked)
					{
						parameter.Set(textNode.Id.IntegerValue.ToString());
					}
				}
				catch (System.Exception ex2)
				{
					string message2 = ex2.Message;
					subTransaction.RollBack();
				}
			}
			catch (System.Exception ex3)
			{
				string message3 = ex3.Message;
				result = false;
			}
			return result;
		}

		private double GetTextWidth(List<string> listText)
		{
			double num = (double)(StringTools.GetStringByteLength(listText[0]) * 10);
			foreach (string str in listText)
			{
				double num2 = (double)(StringTools.GetStringByteLength(str) * 10);
				if (num < num2)
				{
					num = num2;
				}
			}
			return num;
		}

		private XYZ GetRefPoint(Room room)
		{
			Document document = room.Document;
			SpatialElementBoundaryOptions spatialElementBoundaryOptions = new SpatialElementBoundaryOptions();
			IEnumerable<IList<BoundarySegment>> boundarySegments = room.GetBoundarySegments(spatialElementBoundaryOptions);
			List<XYZ> list = new List<XYZ>();
			foreach (IList<BoundarySegment> list2 in boundarySegments)
			{
				foreach (BoundarySegment segment in list2)
				{
					Curve curve = segment.GetCurve();
					list.Add(curve.GetEndPoint(0));
					list.Add(curve.GetEndPoint(1));
				}
			}
			list.Sort((XYZ left, XYZ right) => this.ComparePoint(left, right));
			return list.First<XYZ>().Add(list.Last<XYZ>()) / 2.0;
		}

		private XYZ GetRefPoint(Space space)
		{
			SpatialElementBoundaryOptions spatialElementBoundaryOptions = new SpatialElementBoundaryOptions();
			IEnumerable<IList<BoundarySegment>> boundarySegments = space.GetBoundarySegments(spatialElementBoundaryOptions);
			List<XYZ> list = new List<XYZ>();
			foreach (IList<BoundarySegment> list2 in boundarySegments)
			{
				foreach (BoundarySegment segment in list2)
				{
					Curve curve = segment.GetCurve();
					list.Add(curve.GetEndPoint(0));
					list.Add(curve.GetEndPoint(1));
				}
			}
			list.Sort((XYZ left, XYZ right) => this.ComparePoint(left, right));
			return list.First<XYZ>().Add(list.Last<XYZ>()) / 2.0;
		}

		private int ComparePoint(XYZ pt1, XYZ pt2)
		{
			if (this.IsEqual(pt1.Y, pt2.Y))
			{
				if (this.IsEqual(pt1.X, pt2.X))
				{
					return 0;
				}
				if (this.LessThan(pt1.X, pt2.X))
				{
					return -1;
				}
			}
			else if (this.LessThan(pt1.Y, pt2.Y))
			{
				return -1;
			}
			return 1;
		}

		private bool LessThan(double val1, double val2)
		{
			return val1 - val2 < -0.0001;
		}

		private bool IsEqual(double val1, double val2)
		{
			return !this.LessThan(val1, val2) && !this.LessThan(val2, val1);
		}

		public UIDocument UiDoc { get; set; }

		public string SearchMessage
		{
			get
			{
				return this.searchMessage;
			}
		}

		public double HeatIndex { get; set; }

		public double CoolIndex { get; set; }

		private Document doc;

		private Selection sel;

		private string searchMessage;
	}
}
